import json
from typing import Dict, List, Any, Optional
from pathlib import Path
import logging
from datetime import datetime
import base64
from io import BytesIO
from PIL import Image
import cv2
import numpy as np
from agents.resume_parser import ResumeParser
from agents.knowledge_graph import JobKnowledgeGraph

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("MobileAdapter")

class MobileAdapter:
    """移动端适配器"""
    def __init__(self, kg_client: JobKnowledgeGraph):
        self.kg = kg_client
        self.resume_parser = ResumeParser(kg_client)
        self.cache_dir = Path("b/mobile/cache")
        self._init_cache()
        
    def _init_cache(self):
        """初始化缓存目录"""
        self.cache_dir.mkdir(parents=True, exist_ok=True)
        
    def process_image_upload(self, image_data: str, file_type: str = "jpg") -> Dict[str, Any]:
        """
        处理移动端图片上传
        :param image_data: base64编码的图片数据
        :param file_type: 文件类型(jpg/png)
        :return: 处理结果
        """
        try:
            # 解码图片
            img_bytes = base64.b64decode(image_data)
            img = Image.open(BytesIO(img_bytes))
            
            # 图片预处理
            processed_img = self._preprocess_image(img)
            
            # 保存临时文件
            temp_file = self.cache_dir / f"upload_{datetime.now().strftime('%Y%m%d%H%M%S')}.{file_type}"
            processed_img.save(temp_file)
            
            # 解析简历
            result = self.resume_parser.parse_resume(str(temp_file))
            
            # 清理缓存
            temp_file.unlink()
            
            return {
                "status": "success",
                "result": result,
                "optimized_for_mobile": True
            }
            
        except Exception as e:
            logger.error(f"图片处理失败: {str(e)}")
            return {
                "status": "error",
                "message": str(e)
            }
    
    def _preprocess_image(self, img: Image.Image) -> Image.Image:
        """图片预处理"""
        # 转换为OpenCV格式
        cv_img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        
        # 1. 文档矫正
        gray = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (5, 5), 0)
        edged = cv2.Canny(gray, 75, 200)
        
        # 查找轮廓
        contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]
        
        # 近似多边形
        screen_cnt = None
        for c in contours:
            peri = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02 * peri, True)
            if len(approx) == 4:
                screen_cnt = approx
                break
                
        # 透视变换
        if screen_cnt is not None:
            cv_img = self._four_point_transform(cv_img, screen_cnt.reshape(4, 2))
        
        # 2. 图像增强
        lab = cv2.cvtColor(cv_img, cv2.COLOR_BGR2LAB)
        l, a, b = cv2.split(lab)
        clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
        cl = clahe.apply(l)
        limg = cv2.merge((cl,a,b))
        enhanced = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
        
        # 3. 二值化
        gray = cv2.cvtColor(enhanced, cv2.COLOR_BGR2GRAY)
        _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        
        # 转换回PIL格式
        result = Image.fromarray(cv2.cvtColor(binary, cv2.COLOR_BGR2RGB))
        return result
    
    def _four_point_transform(self, image, pts):
        """四点透视变换"""
        rect = self._order_points(pts)
        (tl, tr, br, bl) = rect
        
        # 计算新图像宽度
        widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
        widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
        maxWidth = max(int(widthA), int(widthB))
        
        # 计算新图像高度
        heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
        heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
        maxHeight = max(int(heightA), int(heightB))
        
        # 目标点坐标
        dst = np.array([
            [0, 0],
            [maxWidth - 1, 0],
            [maxWidth - 1, maxHeight - 1],
            [0, maxHeight - 1]
        ], dtype="float32")
        
        # 计算变换矩阵并应用
        M = cv2.getPerspectiveTransform(rect, dst)
        warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
        
        return warped
    
    def _order_points(self, pts):
        """对矩形四个点进行排序(左上、右上、右下、左下)"""
        rect = np.zeros((4, 2), dtype="float32")
        s = pts.sum(axis=1)
        rect[0] = pts[np.argmin(s)]
        rect[2] = pts[np.argmax(s)]
        
        diff = np.diff(pts, axis=1)
        rect[1] = pts[np.argmin(diff)]
        rect[3] = pts[np.argmax(diff)]
        
        return rect
    
    def get_mobile_optimized_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """优化数据格式供移动端使用"""
        optimized = {}
        
        # 简化数据结构
        if "skills" in data:
            optimized["skills"] = [
                {"name": skill, "category": self._get_skill_category(skill)}
                for skill in data["skills"]
            ]
        
        if "experiences" in data:
            optimized["experiences"] = [
                {
                    "title": exp.get("title", ""),
                    "company": exp.get("company", ""),
                    "duration": f"{exp.get('start_date', '')} - {exp.get('end_date', 'Present')}",
                    "highlights": exp.get("highlights", [])[:3]  # 只取前3条
                }
                for exp in data["experiences"]
            ]
        
        # 添加移动端特有字段
        optimized["mobile_optimized"] = True
        optimized["last_updated"] = datetime.now().isoformat()
        
        return optimized
    
    def _get_skill_category(self, skill: str) -> str:
        """获取技能分类"""
        categories = {
            "programming": ["python", "java", "c++", "javascript"],
            "data": ["sql", "machine learning", "data analysis"],
            "devops": ["docker", "kubernetes", "aws"]
        }
        
        skill_lower = skill.lower()
        for cat, skills in categories.items():
            if skill_lower in skills:
                return cat
        return "other"
    
    def generate_push_notification(self, event_type: str, data: Dict[str, Any]) -> Dict[str, Any]:
        """生成移动端推送通知"""
        templates = {
            "interview_scheduled": {
                "title": "面试安排通知",
                "body": f"您已成功预约{data.get('job_title', '')}岗位的面试，时间: {data.get('time', '')}",
                "priority": "high"
            },
            "application_update": {
                "title": "申请状态更新",
                "body": f"您对{data.get('job_title', '')}岗位的申请状态已更新为: {data.get('status', '')}",
                "priority": "default"
            }
        }
        
        if event_type not in templates:
            logger.warning(f"未知的通知类型: {event_type}")
            return {
                "title": "系统通知",
                "body": json.dumps(data),
                "priority": "default"
            }
        
        return templates[event_type]

if __name__ == "__main__":
    # 示例使用
    kg = JobKnowledgeGraph()
    mobile = MobileAdapter(kg)
    
    # 测试图片处理
    print("\n测试简历图片处理...")
    with open("b/tests/data/sample_resume.jpg", "rb") as img_file:
        img_data = base64.b64encode(img_file.read()).decode("utf-8")
    
    result = mobile.process_image_upload(img_data)
    print(f"解析结果状态: {result['status']}")
    if result["status"] == "success":
        print(f"识别到技能: {', '.join(result['result']['skills'][:3])}...")
    
    # 测试数据优化
    print("\n测试移动端数据优化...")
    sample_data = {
        "skills": ["Python", "SQL", "Docker"],
        "experiences": [
            {
                "title": "Software Engineer",
                "company": "Tech Inc.",
                "start_date": "2020-01",
                "end_date": "2022-12",
                "highlights": [
                    "Developed web applications using Django",
                    "Optimized database queries",
                    "Implemented CI/CD pipeline"
                ]
            }
        ]
    }
    optimized = mobile.get_mobile_optimized_data(sample_data)
    print("优化后的数据:")
    print(json.dumps(optimized, indent=2))
    
    # 测试通知生成
    print("\n测试推送通知生成...")
    notification = mobile.generate_push_notification(
        "interview_scheduled",
        {"job_title": "Senior Python Developer", "time": "2023-12-15 14:00"}
    )
    print(f"通知标题: {notification['title']}")
    print(f"通知内容: {notification['body']}")